iT邦幫忙

2023 iThome 鐵人賽

DAY 1
0
自我挑戰組

Django系列 第 14

Day14~Django 漫漫長路- 入木三分serializer-part2

  • 分享至 

  • xImage
  •  

大家好,我是Leo
今天要來講解的如何在serializer 引用 serializer的其他種用法/images/emoticon/emoticon30.gif
OK~~~ Let's go now!!!


今天我們也是跟昨天一樣製作一個auth list內要包含的是users、user_certificate及user_photo的資訊,如果我們想直接取到fullName,及我們要將薪水以每5000元分為一個等級,該如何製作serializer,我們今天會使用另一種方式來達到顯示的效果。

確認資料庫有無資料

概念圖如下(黃色的部份是我們希望回傳的欄位)

https://ithelp.ithome.com.tw/upload/images/20230117/20154853FnIbGz57Wn.jpg

因為昨天確認過有無資料,這邊就不重複確認了我們直接進入到serializer的環節。


Serializers

serializers/user_list_ser.py

from rest_framework import serializers
from website.models import (
    Users,
    User_Photo,
    User_Certificates
)

class PhotoListSerializer(serializers.ModelSerializer):
    class Meta:
        model = User_Photo
        exclude =('created_at','deleted_at')

class PhotoIdsSerializer(serializers.ModelSerializer):
    class Meta:
        model = User_Photo
        fields = ('id',)

    def to_representation(self, instance):
        return instance.id


class CertificateListSerializer(serializers.ModelSerializer):
    class Meta:
        model = User_Certificates
        exclude = ('created_at', 'deleted_at')

class CertificateIdsSerializer(serializers.ModelSerializer):
    class Meta:
        model = User_Certificates
        exclude = ('created_at', 'deleted_at')

    def to_representation(self, instance):
        return instance.id
        
class UserListSecondWaySerializer(serializers.ModelSerializer):
    userName = serializers.ReadOnlyField(source='auth_user.username')
    email = serializers.ReadOnlyField(source='auth_user.email')
    roleName = serializers.ReadOnlyField(source='role.name')
    roleSalary = serializers.ReadOnlyField(source='role.salary')
    fullName = serializers.SerializerMethodField()
    userPhotos = serializers.SerializerMethodField()
    userPhotosIds = serializers.SerializerMethodField()
    userCertificates = serializers.SerializerMethodField()
    userCertificateIds = serializers.SerializerMethodField()

    class Meta:
        model = Users
        fields = ("id",
                  "status",
                  "userName",
                  "email",
                  "tel",
                  "roleName",
                  "roleSalary",
                  "fullName",
                  "userPhotosIds",
                  "userPhotos",
                  "userCertificateIds",
                  "userCertificates"
                  )

    def get_userPhotos(self,instance):
        userPhotos = instance.users.all().order_by("id")
        return PhotoListSerializer(userPhotos, read_only=True, many=True).data

    def get_userPhotosIds(self, instance):
        userPhotosIds = instance.users.all().order_by("id")
        return PhotoIdsSerializer(userPhotosIds, read_only=True, many=True).data

    def get_userCertificateIds(self, instance):
        userCertificateIds = instance.user_certicicate_users.all().order_by("id")
        return CertificateIdsSerializer(userCertificateIds, read_only=True, many=True).data

    def get_userCertificates(self, instance):
        userCertificates = instance.user_certicicate_users.all().order_by("id")
        return CertificateListSerializer(userCertificates, read_only=True, many=True).data

    def get_fullName(self, instance):
        name = instance.auth_user.last_name + instance.auth_user.first_name
        return name

    def to_representation(self,instance):
        data = super().to_representation(instance)
        data['roleSalaryLevel'] = dict(data)['roleSalary']//5000
        return data

這邊有個重點,instance後的參數,需接當初在設計model時的related_name,以下是user_photo_model.py

https://ithelp.ithome.com.tw/upload/images/20230117/20154853Rnv5CDisLT.jpg

get_field 用法需要跟上面的serializer定義的名稱一樣,也就是說 get_fullName 上面就需要有一個fullName的欄位,會接function回傳的資訊。

to_representation(self,instance) 可以改變序列化的輸出,透過super()繼承,增加一個欄位為roleSalaryLevel,等級為每5000元為一個等級

serializers/init.py

from .user_list_ser import *

Views

views/user_list.py

from rest_framework import permissions
from rest_framework.views import APIView
from website.models import Users
from website.serializers import UserListSerializer,UserListSecondWaySerializer
from rest_framework.response import Response

class UserListAPIView(APIView):
    permission_classes = (permissions.AllowAny,)
    authentication_classes = []

    def post(self, request):
        users = Users.objects.all()
        serializer_users = UserListSecondWaySerializer(
            users, many=True, context={"request": request}
        )
        return Response(serializer_users.data)

views/init.py

from .user_list import *

url

urls.py

from django.urls import path
from website.views import UserListAPIView

path('api/user/list',UserListAPIView.as_view(),name='api-user-list')

Postman測試

https://ithelp.ithome.com.tw/upload/images/20230117/20154853l6qUl6LJ7X.jpg

json

[
    {
        "id": 1,
        "status": 0,
        "userName": "leo1",
        "email": "a@gamil.com",
        "tel": "0987654321",
        "roleName": "parttime",
        "roleSalary": 10000.0,
        "fullName": "leeleo",
        "userPhotosIds": [
            1
        ],
        "userPhotos": [
            {
                "id": 1,
                "file_name": "lbj",
                "file_path": "/media/users/1/4d27a17b-4965-4383-8373-6fba575e3096.jpg",
                "user": 1
            }
        ],
        "userCertificateIds": [
            1,
            2
        ],
        "userCertificates": [
            {
                "id": 1,
                "file_name": "leo",
                "file_path": "/media/users/1/c0c4adea-3f21-4011-a0a2-019eb92515a8.jpg",
                "user": 1
            },
            {
                "id": 2,
                "file_name": "leo",
                "file_path": "/media/users/1/110e6360-c3a1-4619-b855-282242a55c5e.jpg",
                "user": 1
            }
        ],
        "roleSalaryLevel": 2.0
    },
    {
        "id": 2,
        "status": 0,
        "userName": "leo",
        "email": "a@gamil.com",
        "tel": "0987654321",
        "roleName": "parttime",
        "roleSalary": 10000.0,
        "fullName": "leeleo",
        "userPhotosIds": [
            3,
            4
        ],
        "userPhotos": [
            {
                "id": 3,
                "file_name": "lin",
                "file_path": "/media/users/2/e5316f6e-4410-4e93-a7f7-9bf5ff3831cc.jpg",
                "user": 2
            },
            {
                "id": 4,
                "file_name": "lin",
                "file_path": "/media/users/2/84854e94-eada-4940-b0d8-ea97ec25d41d.jpg",
                "user": 2
            }
        ],
        "userCertificateIds": [
            3
        ],
        "userCertificates": [
            {
                "id": 3,
                "file_name": "leo2",
                "file_path": "/media/users/2/53f26df3-0213-4d02-aeb2-1e4a3c8816b6.jpg",
                "user": 2
            }
        ],
        "roleSalaryLevel": 2.0
    },
    {
        "id": 3,
        "status": 0,
        "userName": "leo2",
        "email": "a@gamil.com",
        "tel": "0987654321",
        "roleName": "parttime",
        "roleSalary": 10000.0,
        "fullName": "lee2leo2",
        "userPhotosIds": [
            2
        ],
        "userPhotos": [
            {
                "id": 2,
                "file_name": "yun",
                "file_path": "/media/users/3/6a5a0079-a2c3-4647-8ad0-0d1ba05afd5d.jpg",
                "user": 3
            }
        ],
        "userCertificateIds": [],
        "userCertificates": [],
        "roleSalaryLevel": 2.0
    },
    {
        "id": 4,
        "status": 0,
        "userName": "leo3",
        "email": "a@gamil.com",
        "tel": "0987654321",
        "roleName": "engineer",
        "roleSalary": 20000.0,
        "fullName": "lee3leo3",
        "userPhotosIds": [],
        "userPhotos": [],
        "userCertificateIds": [],
        "userCertificates": [],
        "roleSalaryLevel": 4.0
    },
    {
        "id": 5,
        "status": 0,
        "userName": "leo4",
        "email": "a@gamil.com",
        "tel": "0987654321",
        "roleName": "engineer",
        "roleSalary": 20000.0,
        "fullName": "lee4leo4",
        "userPhotosIds": [],
        "userPhotos": [],
        "userCertificateIds": [],
        "userCertificates": [],
        "roleSalaryLevel": 4.0
    },
    {
        "id": 6,
        "status": 0,
        "userName": "leo5",
        "email": "a@gamil.com",
        "tel": "0987654321",
        "roleName": "manage",
        "roleSalary": 30000.0,
        "fullName": "lee5leo5",
        "userPhotosIds": [],
        "userPhotos": [],
        "userCertificateIds": [],
        "userCertificates": [],
        "roleSalaryLevel": 6.0
    }
]

透過這種方式也可以增減serializers的field,或自訂義field


今天透過serializer將我們要的fields欄位全部回傳回來,以及新增一個roleSalaryLevel field與定義一個fullName field,透過今天的方式,可以自行修改及增減serializers,是一個滿實用的分法
明天我想介紹的是如果我們有多個db,我們不可能一個專案for一個db,我們要同時使用ORM連接多個DB的方式
我們明天見,各位掰掰~~~/images/emoticon/emoticon29.gif


上一篇
Day13~Django 漫漫長路- 入木三分serializer-part1
下一篇
Day15~Django 漫漫長路-使用多個database 取出資料
系列文
Django30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言